package com.zhengbing.tj.design.async;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.concurrent.CompletableFuture;

/**
 * 异步服务类
 * 演示Spring异步执行的多种使用方式
 * 
 * @author zhengbing
 * @since 2024-08-21
 */
@Service
public class AsyncService {
    
    private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);

    /**
     * 简单的异步方法
     * 使用@Async注解实现异步执行
     *
     * @param message 处理消息
     */
    @Async
    public void simpleAsyncTask(String message) {
        logger.info("开始执行简单异步任务: {}", message);
        try {
            // 模拟耗时操作
            Thread.sleep(3000);
            logger.info("简单异步任务完成: {}", message);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.error("异步任务被中断", e);
        }
    }

    /**
     * 带返回值的异步方法
     * 使用CompletableFuture包装异步结果
     *
     * @param number 计算数字
     * @return CompletableFuture<Integer> 异步计算结果
     */
    @Async
    public CompletableFuture<Integer> calculateAsync(int number) {
        logger.info("开始计算数字: {} 的平方", number);
        try {
            Thread.sleep(2000); // 模拟计算耗时
            int result = number * number;
            logger.info("计算完成: {}² = {}", number, result);
            return CompletableFuture.completedFuture(result);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.error("计算任务被中断", e);
            CompletableFuture<Integer> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        }
    }

    /**
     * 使用自定义线程池的异步方法
     * 指定使用emailExecutor线程池
     *
     * @param email 邮件地址
     * @param content 邮件内容
     */
    @Async("emailExecutor")
    public void sendEmailAsync(String email, String content) {
        logger.info("开始发送邮件到: {}", email);
        try {
            // 模拟邮件发送耗时
            Thread.sleep(4000);
            logger.info("邮件发送成功到: {}", email);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.error("邮件发送被中断", e);
        }
    }

    /**
     * 批量异步任务
     * 同时处理多个异步任务
     *
     * @param items 处理项目列表
     */
    @Async
    public void processBatchAsync(String[] items) {
        logger.info("开始批量处理 {} 个项目", items.length);
        
        CompletableFuture<?>[] futures = new CompletableFuture[items.length];
        
        for (int i = 0; i < items.length; i++) {
            final int index = i;
            final String item = items[i];
            
            futures[i] = CompletableFuture.runAsync(() -> {
                try {
                    logger.info("开始处理项目[{}]: {}", index + 1, item);
                    Thread.sleep(1000); // 模拟处理时间
                    logger.info("完成处理项目[{}]: {}", index + 1, item);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    logger.error("处理项目[{}]被中断", index + 1, e);
                }
            });
        }
        
        // 等待所有任务完成
        CompletableFuture.allOf(futures).join();
        logger.info("所有批量任务完成");
    }

    /**
     * 异常处理的异步方法
     * 演示异步任务中的异常处理
     *
     * @param shouldFail 是否故意失败
     * @return CompletableFuture<String> 异步结果
     */
    @Async
    public CompletableFuture<String> riskyAsyncTask(boolean shouldFail) {
        logger.info("开始执行风险任务，shouldFail: {}", shouldFail);
        
        try {
            Thread.sleep(1500);
            
            if (shouldFail) {
                throw new RuntimeException("故意抛出异常用于测试");
            }
            
            String result = "风险任务执行成功";
            logger.info("风险任务完成: {}", result);
            return CompletableFuture.completedFuture(result);
            
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            logger.error("风险任务被中断", e);
            CompletableFuture<String> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        } catch (Exception e) {
            logger.error("风险任务执行失败", e);
            CompletableFuture<String> future = new CompletableFuture<>();
            future.completeExceptionally(e);
            return future;
        }
    }
}